package JDBC;

import java.sql.*;


/*
一个MySQL的JDBC的驱动就是一个jar包，它本身也是纯Java编写的。
我们自己编写的代码只需要引用Java标准库提供的java.sql包下面的相关接口，由此再间接地通过MySQL驱动的jar包通过网络访问MySQL服务器，
所有复杂的网络通讯都被封装到JDBC驱动中，因此，Java程序本身只需要引入一个MySQL驱动的jar包就可以正常访问MySQL服务器

1. 通过Connection提供的createStatement()方法创建一个Statement对象，用于执行一个查询；
2. 执行Statement对象提供的executeQuery("SELECT * FROM students")并传入SQL语句，执行查询并获得返回的结果集，使用ResultSet来引用这个结果集；
3. 反复调用ResultSet的next()方法并读取每一行结果。
*/



//连接信息
class t01a {
    // JDBC连接的URL, 不同数据库有不同的格式:
    String JDBC_URL = "jdbc:mysql://10.1.5.225:3306/mysql";
    String JDBC_USER = "grafana";
    String JDBC_PASSWORD = "grafana123";
}
class t011 extends t01a {
    //手动关闭连接
    public void a01() throws Exception

    {
        System.out.println("a01");
        //加载MySql驱动
         Class.forName("com.mysql.cj.jdbc.Driver");

        // 获取连接:
        Connection conn = DriverManager.getConnection(JDBC_URL, JDBC_USER, JDBC_PASSWORD);
        // 核心代码是DriverManager提供的静态方法getConnection()。DriverManager会自动扫描classpath，找到所有的JDBC驱动，然后根据我们传入的URL自动挑选一个合适的驱动。

        // TODO: 访问数据库...
        Statement stmt = null;
        stmt = conn.createStatement();
        String sql;
        sql = "SELECT host,user from user;";
        ResultSet rs = stmt.executeQuery(sql);
        while(rs.next()){
            // 通过字段检索
            String host = rs.getString("host");
            String user = rs.getString("user");

            // 输出数据
            System.out.print(" 主机: " + host);
            System.out.print(" 用户: " + user);
            System.out.print("\n");
        }
        // 关闭连接:
        conn.close();
    }

    //使用try (resource)来自动释放JDBC连接
    public void a02() throws Exception

    {
        System.out.println("a02");
        // 我们使用 Class.forName() 方法来加载 MySQL 驱动程序。如果加载失败，将抛出 ClassNotFoundException 异常。
        try {
            // 加载 MySQL 驱动程序
            Class.forName("com.mysql.cj.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            System.err.println("无法加载数据库驱动程序");
            e.printStackTrace();
        }
    /*
    注意要点：
        Statement和ResultSet都是需要关闭的资源，因此嵌套使用try (resource)确保及时关闭；
        rs.next()用于判断是否有下一行记录，如果有，将自动把当前行移动到下一行（一开始获得ResultSet时当前行不是第一行）；
        ResultSet获取列时，索引从1开始而不是0；
        必须根据SELECT的列的对应位置来调用getLong(1)，getString(2)这些方法，否则对应位置的数据类型不对，将报错。
     */
        try (Connection conn = DriverManager.getConnection(JDBC_URL, JDBC_USER, JDBC_PASSWORD)) {
            try (Statement stmt = conn.createStatement()) {
                try (ResultSet rs = stmt.executeQuery("SELECT host, user FROM user WHERE user='root'")) {
                    while (rs.next()) {
                        String host = rs.getString(1);
                        String user = rs.getString(2);
                        System.out.print(" 主机: " + host);
                        System.out.print(" 用户: " + user);
                        System.out.print("\n");
                    }
                }
            }
        }
    }

    // 完全避免SQL注入:使用Statement的代码改为使用PreparedStatement
    public void a03() throws Exception

    {
        System.out.println("a03");
        // 使用Java对数据库进行操作时，必须使用PreparedStatement，严禁任何通过参数拼字符串的代码！
        try (Connection conn = DriverManager.getConnection(JDBC_URL, JDBC_USER, JDBC_PASSWORD)) {
            try (PreparedStatement ps = conn.prepareStatement("SELECT id, host, user FROM information_schema.processlist WHERE host=?")) {
                ps.setObject(1, "localhost"); // 注意：索引从1开始
                try (ResultSet rs = ps.executeQuery()) {
                    while (rs.next()) {
                        long id = rs.getLong(1); // 注意：索引从1开始
                        String host = rs.getString(2);
                        String user = rs.getString(3);
                        System.out.print(" id: " + id);
                        System.out.print(" 主机: " + host);
                        System.out.print(" 用户: " + user);
                        System.out.print("\n");
                    }
                }
            }
        }
    }
}


public class t01 extends t011{
    public static void main(String[] args) throws Exception{
        Class.forName("com.mysql.cj.jdbc.Driver");
        t011 t= new t011();
        t.a01();
        t.a02();
        t.a03();
    }
}